﻿using Arch.Core;
using Arch.Core.Extensions;
using Meow.Core.Graphics;
using Meow.Core.Graphics.Renderables;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics.Arm;


namespace Meow.Core.Simulation;



public class CameraRenderSystem : ECS_System, IRenderSystem
{
    QueryDescription cameraQuery = new QueryDescription()
                                        .WithAll<SimpleCamera>();

    QueryDescription renderableQuery = new QueryDescription()
                                    .WithAll<C_Renderable, WithMesh, C_Position, C_Scale, C_Rotation>();

    List<Renderable> renderables = new List<Renderable>();

    public CameraRenderSystem(World world, Scene scene) : base(world, scene)
    {
    }

    void IRenderSystem.Render(Microsoft.Xna.Framework.GraphicsDeviceManager gdm, Microsoft.Xna.Framework.GameTime gameTime, float totalElapsedTime, int tick)
    {
        world.Query(in cameraQuery, (ref SimpleCamera camera) =>
        {
            gdm.GraphicsDevice.Viewport = camera.Viewport;

            var camForRender = camera.GetRenderInfo();

            // TODO: Lights, Shadows, etc


            renderables.Clear();

            var entities = camera.GetEntitiesInSight();
            for (var i = 0; i < entities.Count; ++i)
            {
                var components = entities[i].Get<C_Renderable, C_Position, C_Scale, C_Rotation, WithMesh>();

                renderables.Add(new MeshRenderable(components.t4.Value.mesh,
                    components.t4.Value.material,
                    XnaMathExts.CreateFromRotScalePos(
                        components.t3.Value.Value,
                        components.t2.Value.Value,
                        components.t1.Value.Value + components.t4.Value.Offset)));
            }

            //world.Query(in renderableQuery, (ref WithMesh mesh, ref C_Position pos, ref C_Scale scale, ref C_Rotation rot) =>
            //{
            //    renderables.Add(new MeshRenderable(mesh.mesh,
            //        mesh.material,
            //        XnaMathExts.CreateFromRotScalePos(rot.Value, scale.Value, pos.Value + mesh.Offset)));

            //});

            using (gdm.GraphicsDevice.AnisoSampleState())
            {
                for (var i = 0; i < renderables.Count; ++i)
                {
                    renderables[i].Draw(camForRender, gdm);
                }

            }

        });
    }
}

